package com.example.hosrxjavaapplication.slice;

import com.example.hosrxjavaapplication.Constant;
import com.example.hosrxjavaapplication.ResourceTable;
import com.example.hosrxjavaapplication.inject.InjectUtils;
import com.example.hosrxjavaapplication.inject.SliceInjectView;
import com.example.hosrxjavaapplication.inject.SliceInjectViewClick;
import com.example.hosrxjavaapplication.observable.*;
import com.example.hosrxjavaapplication.util.StringUtils;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ProgressBar;
import ohos.agp.components.Text;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.hiviewdfx.HiLog;

/**
 * create by chenjiayou on 2021/2/19
 */
public class RxJavaAbilitySlice extends AbilitySlice {

    @SliceInjectView(ResourceTable.Id_progressText)
    Text mProgressText;

    @SliceInjectView(ResourceTable.Id_progress)
    ProgressBar mProgress;

    @SliceInjectView(ResourceTable.Id_result)
    Text mResultText;

    int mTotal = 100;
    int mIndex = 10;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_rx_java);
        InjectUtils.inject(this);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }


    @SliceInjectViewClick({ResourceTable.Id_loop, ResourceTable.Id_doWork, ResourceTable.Id_doFor, ResourceTable.Id_doTotal, ResourceTable.Id_close})
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_loop:
                loadThread();
                break;

            case ResourceTable.Id_doWork:
                doWork();
                break;

            case ResourceTable.Id_doFor:
                doFor();
                break;
            case ResourceTable.Id_doTotal:
                doTotal();
                break;

            case ResourceTable.Id_close:
                terminate();
                break;
        }
    }

    private void doWork() {
        Observables.createWorkObservable(this)
                .work(new ObservableWork<Integer, Integer>() {

                    @Override
                    public Integer doWork(Integer integer) {
                        return ++mIndex;
                    }
                })
                .work(new ObservableWork<String, Integer>() {

                    @Override
                    public String doWork(Integer integer) {
                        return "this calc result : " + integer;
                    }
                })
                .work(new ObservableWork<String, String>() {

                    @Override
                    public String doWork(String result) {
                        return "I got " + result;
                    }
                })
                .work(new ObservableWork<String, String>() {

                    @Override
                    public String doWork(String result) {
                        return "I am sure " + result;
                    }
                })
                .observeOn(Schedulers.UI)
                .subscribeOn(Schedulers.IO)
                .interval(20)
                .subscribe(new ObserverImpl() {
                    @Override
                    public void onSubscribe(Object object) {
                        String result = object.toString();
                        mResultText.setText(result);
                        HiLog.info(Constant.label, "onSubscribe =>  " + result);
                    }
                });
    }

    public void doFor() {
        Observables.createObservable(this,
                new ObservableOnSubscribe<Integer>() {
                    @Override
                    public void subscribe(ObservableEmitter<Integer> emitter) {
                        for (int i = 0; i < mTotal; i++) {
                            emitter.onNext(i);
                        }
                        emitter.onComplete();
                    }
                })
                .observeOn(Schedulers.UI)
                .subscribeOn(Schedulers.IO)
                .interval(20)
                .subscribe(new ObserverImpl<Integer>() {
                    @Override
                    public void onNext(Integer progress) {
                        String percentage = StringUtils.calcPercentage(progress, mTotal);
                        HiLog.info(Constant.label, "onNext => " + percentage + "  thread on " + Thread.currentThread());
                        mProgressText.setText(percentage + "%");
                        mProgress.setProgressValue(progress + 1);
                    }

                    @Override
                    public void onComplete() {
                        HiLog.info(Constant.label, "onComplete => thread on " + Thread.currentThread());
                        mProgressText.setText("100%");
                        mProgress.setProgressValue(100);
                    }
                });
    }


    public void doTotal() {
        Observables.createObservable(this,
                new ObservableOnSubscribe<Integer>() {
                    @Override
                    public void subscribe(ObservableEmitter<Integer> emitter) {
                        for (int i = 0; i < mTotal; i++) {
                            emitter.onNext(i);
                        }
                        emitter.onComplete();
                    }
                })
                .work(new ObservableWork<Integer, Integer>() {

                    @Override
                    public Integer doWork(Integer integer) {
                        return ++mIndex;
                    }
                })
                .work(new ObservableWork<String, Integer>() {

                    @Override
                    public String doWork(Integer integer) {
                        return "this calc result : " + integer;
                    }
                })
                .work(new ObservableWork<String, String>() {

                    @Override
                    public String doWork(String result) {
                        return "I got " + result;
                    }
                })
                .work(new ObservableWork<String, String>() {

                    @Override
                    public String doWork(String result) {
                        return "I am sure " + result;
                    }
                })
                .observeOn(Schedulers.UI)
                .subscribeOn(Schedulers.IO)
                .interval(20)
                .subscribe(new ObserverImpl<Integer>() {
                    @Override
                    public void onNext(Integer progress) {
                        String percentage = StringUtils.calcPercentage(progress, mTotal);
                        HiLog.info(Constant.label, "onNext => " + percentage + "  thread on " + Thread.currentThread());
                        mProgressText.setText(percentage + "%");
                        mProgress.setProgressValue(progress + 1);
                    }

                    @Override
                    public void onComplete() {
                        HiLog.info(Constant.label, "onComplete => thread on " + Thread.currentThread());
                        mProgressText.setText("100%");
                        mProgress.setProgressValue(100);
                    }

                    @Override
                    public void onSubscribe(Object object) {
                        String result = object.toString();
                        mResultText.setText(result);
                        HiLog.info(Constant.label, "onSubscribe =>  " + result);
                    }
                });
    }


    /**
     * 线程和UI线程交互：
     * <p>
     * 1. UITaskDispatcher更新UI
     * <p>
     * 同步任务 = > 异步更新UI
     * <p>
     * getGlobalTaskDispatcher(TaskPriority.DEFAULT).syncDispatch() = > getUITaskDispatcher().asyncDispatch()
     * <p>
     * 异步任务 = > 同步更新UI
     * <p>
     * getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch() = > getUITaskDispatcher().syncDispatch()
     * <p>
     * 总结 ： 外循环一定是asyncDispatch 对应内循环的 asyncDispatch 或者 syncDispatch都可以 但是如果外循环是 syncDispatch 则内部 不论是asyncDispatch 或者 syncDispatch都不行
     */
    public void loadThread() {
        getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> {
            for (int i = 0; i < mTotal; i++) {
                int finalI = i;
                getUITaskDispatcher().syncDispatch(() -> { //  getUITaskDispatcher().asyncDispatch 也可以
                    mProgressText.setText((finalI + 1) + "%");
                    mProgress.setProgressValue(finalI);
                });
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
